/******************************************************************************
**  $Id: dc_log_api.h,v 1.6 2010-04-25 18:41:13 kimm Exp $                                                                     **
**                                                                           **
**                 Proprietary and Confidential Information                  **
**                                                                           **
**                 Copyright (c) SigmaTel, Inc. Unpublished                  **
**                                                                           **
** This source code and the algorithms implemented therein constitute        **
** confidential information and may compromise trade secrets of SigmaTel,    **
** Inc. or its associates, and any unauthorized use thereof is prohibited.   **
**                                                                           **
******************************************************************************/

#ifndef _dc_log_h
# define _dc_log_h

/*
  External interface declarations for the Digicolor debug logging facility.

  See dc_log_pvt.h for macros dealing with log buffer format.

*/


/*
  Flag to be passed to dc_log_initialize indicating that logging from FIRQ
  handlers should be handled.
*/

# define DC_LOG_FLAG_NONE  0UL  //No special flags
# define DC_LOG_FLAG_FIRQ  1UL  //Allow FIRQ handlers to use the log system

/* Identifying string for header record 0. */
# define DC_LOG_MAGIC "DIGICOLOR LOG 1.0       "

/*
  Size of each log record, in bytes.  This cannot be changed without reworking
  some of the code in dc_log.c
*/
# define DC_LOG_RECORD_SIZE 32

/*
  The size of the record-specific payload.  8 bytes are used for timestamp,
  sequence number, and log id.
*/
# define DC_LOG_PAYLOAD_SIZE (DC_LOG_RECORD_SIZE - 8)

/*
  The size of a log id name field
*/
# define DC_LOG_NAME_SIZE 12

/*
  Number of records in the header section.
*/
# define DC_LOG_HEADER_RECORDS 3

/*
  Size of formatting buffer in dc_log_printf
*/
# define DC_LOG_PRINTF_SIZE 80

/*
  State vales for the log struct itself, not encoded in the log buffer.
*/
# define DC_LOG_STATE_ENABLED 0x676f4c01
# define DC_LOG_STATE_DISABLED 0x676f4c00

/*
  This state is not supported yet, but should be.  It means post log
  records but do not do sprintf formatting on them.  This is intended
  for high traffic logs that are normally read only after an error, so
  that most of the formatting is wasted.  Some additional bookkeeping
  in the log struct will be necessary so that we know which records
  have been formatted and which not.
*/
# define DC_LOG_STATE_DEFERRED 0x676f4c02

/* True iff state looks valid */
# define DC_LOG_STATE_OK(state) (0x676f4c00 == (0xfffffffe & (state)))

/* Returned from dc_log_state_set in case of error, not a valid state. */
# define DC_LOG_STATE_ERROR 0


/* 
   Definitions to support classification of log messages.
   The macros below are meant to be prepended to log format strings.
*/

# define DC_LOG_LEVEL_CHAR_P(c) (0x10 == (0xf8 & (c)))
# define DC_LOG_LEVEL(c) (0x3 & (unsigned)(c))

# define DC_LOG_CHAR_CRITICAL '\x10'
# define DC_LOG_CHAR_ERROR    '\x11'
# define DC_LOG_CHAR_WARNING  '\x12'
# define DC_LOG_CHAR_NOTICE   '\x13'

# define DC_LOG_CHAR_DEBUG0   '\x14'
# define DC_LOG_CHAR_DEBUG1   '\x15'
# define DC_LOG_CHAR_DEBUG2   '\x16'
# define DC_LOG_CHAR_DEBUG3   '\x17'

# define DC_LOG_CRITICAL "\x10"
# define DC_LOG_ERROR    "\x11"
# define DC_LOG_WARNING  "\x12"
# define DC_LOG_NOTICE   "\x13"

/*
  group here should be a token without embedded whitespace and of
  at most 8 characters in length.  Internal group identifiers for
  SDK components should begin with and underscore (_).
*/
# define DC_LOG_DEBUG0(group) "\x14" #group " "
# define DC_LOG_DEBUG1(group) "\x15" #group " "
# define DC_LOG_DEBUG2(group) "\x16" #group " "
# define DC_LOG_DEBUG3(group) "\x17" #group " "


/*
  fmt should be a string, evaluate to nonzero if that string denotes a
  debugging message format string.
*/
# define DC_LOG_DEBUG_P(fmt) (0x14==(0xfc & (fmt)[0]))

typedef struct DC_LOG {
    // Indicates that log has been initialized, is disabled, ...
    UINT32 state;

    // Base of the log buffer header
    UINT8 *header;

    // Pointer to message count in header.
    UINT32 *header_message_count;

    // Base of the log id table
    UINT8 *id_table;

    // Size of the log id table in records
    UINT32 id_table_records;

    // Base of the circular log buffer
    UINT8 *msg_buffer;

    // The index to the next circular log buffer record to write
    UINT32 msg_index;

    // The number of records in the circular log buffer
    UINT32 msg_records;

    // The next sequence number to use in the circular log buffer
    UINT16 sequence;

    // Interrupt status value to use while writing log records.
    // This may or may not disable FIRQ, depending on the flags
    // passed to dc_log_initialize.
    UINT32 int_disable;

    // True iff dc_log_initialize told us that FIRQ handlers might log.
    int firq_ok;

    /*
      Limits of the log id freelist:
      Entries are removed from the head, and added at the tail.
      zero is not a valid index, and is used to indicate an empty
      list.
    */
    unsigned int id_freehead;
    unsigned int id_freetail;
} DC_LOG_t; 


typedef struct DC_LOG_GROUP {
    union {
        char str[8];
        UINT32 dw[2];
    } name;
    UINT8 host_level;
    UINT8 fw_level;
    UINT16 next;
} DC_LOG_GROUP_t;


/* Exported function prototypes */

/*
  The usual application log interface.
*/
DC_RETURN_CODE dc__log_header_sizes(UINT8 *buffer, UINT32 size,
                                   UINT32 *rec_size, UINT32 *header_records, 
                                   UINT32 *id_records, UINT32 *msg_records);

DC_RETURN_CODE dc_log_initialize(void *address, UINT32 size, UINT32 num_ids, UINT32 flags);

DC_RETURN_CODE dc_log_information(UINT8 **address, UINT32 *size);

DC_RETURN_CODE dc_log_binary(void *msg, UINT32 size);

DC_RETURN_CODE dc_log_printf(char *format, ...);
DC_RETURN_CODE dc_log_printf2(char *format, ...);
DC_RETURN_CODE dc_log_printf3(char *format, ...);

DC_RETURN_CODE dc_log_string(char *str);

/* Required only for dbgmon support, do not call if dbgmon support is not present. */
DC_RETURN_CODE dc_log_export(void);

/*
  Functions for using non-default (SPecial) log buffers.
*/

DC_LOG_t *dc__log_default(void);

DC_RETURN_CODE dc__log_sp_initialize(DC_LOG_t *log, void *address, UINT32 size, UINT32 flags);

DC_RETURN_CODE dc__log_sp_information(DC_LOG_t *log, UINT8 **address, UINT32 *size);

DC_RETURN_CODE dc__log_sp_binary(DC_LOG_t *log, void *msg, UINT32 size);

DC_RETURN_CODE dc__log_sp_string(DC_LOG_t *log, char *str);

DC_RETURN_CODE dc__log_sp_printf(DC_LOG_t *log, char *format, ...);

UINT32 dc_log_state_set(DC_LOG_t *log, UINT32 new_state);

/* Required only for dbgmon support, do not call if dbgmon support is not present. */
DC_RETURN_CODE dc__log_sp_export(DC_LOG_t *log, char *dbg_name);

/*
  Functions to support log classification based on severity and group.
*/

/* Use the block of memory passed in as the group table. */
DC_RETURN_CODE dc_log_group_table_register(DC_LOG_GROUP_t *tab, UINT16 n_groups);

/* Return the address and size of the group table, so it may be exported. */
DC_RETURN_CODE dc__log_group_table_info_get(DC_LOG_GROUP_t **tab, UINT16 *n_groups);

/* Create a log group, usable as either dynamic or static. */
DC_RETURN_CODE dc_log_group_register(char *str);

/* Set the dynamic (thread-local) log group. */
DC_RETURN_CODE dc_log_group_set(char *str);

/* Get the name of the current dynamic (thread-local) log group. */
DC_RETURN_CODE dc__log_group_get(char **str);

/*
  Set the firmware-controlled level of the indicated log group.
*/
DC_RETURN_CODE dc_log_level_set(char *group_name, char *str);

/*
  Return true iff the debug print with format given by str should be printed.
  The first character of str must be a log level debug print character.
*/
int dc_log_enabled(char *str);

void dc_debug_data_print(char *what, UINT8 *s, int n);
void dc_debug_char_print(char *s, int n);
void dc_debug_print_line(char fill);

#endif //ndef _dc_log_h
